package xutil

import (
	"crypto/md5"
	"encoding/base64"
	"io"
	"math"
	"os"
)

type S查询签署 struct {
	SignFlowStatus int32 `json:"signFlowStatus,omitempty"`
}
type S查询签署返回 struct {
	S易签宝基础
	Data S查询签署 `json:"data,omitempty"`
}

type S创建个人信息 struct {
	AccountId string `json:"accountId,omitempty"`
}
type S创建个人信息返回 struct {
	S易签宝基础
	Data S创建个人信息 `json:"data,omitempty"`
}
type S签署链接 struct {
	ShortUrl string `json:"shortUrl,omitempty"`
	Url      string `json:"url,omitempty"`
}
type S签署链接返回 struct {
	S易签宝基础
	Data S签署链接 `json:"data,omitempty"`
}

type S文件上传 struct {
	FileId        string `json:"fileId,omitempty"`
	FileUploadUrl string `json:"fileUploadUrl,omitempty"`
}
type S签署信息 struct {
	SignFlowId string `json:"signFlowId,omitempty"`
}
type S签署信息返回 struct {
	S易签宝基础
	Data S签署信息 `json:"data,omitempty"`
}
type S文件上传返回 struct {
	S易签宝基础
	Data S文件上传 `json:"data,omitempty"`
}

type S文件上传结果 struct {
	Msg     string `json:"msg,omitempty"`
	ErrCode int    `json:"errCode,omitempty"`
}

type S易签宝基础 struct {
	Code    int    `json:"code,omitempty"`
	Message string `json:"message,omitempty"`
	Success bool   `json:"success,omitempty"`
}

type S查找关键词返回 struct {
	S易签宝基础
	Data S查找关键词 `json:"data,omitempty"`
}

type S查找关键词 struct {
	KeywordPositions []S关键词信息 `json:"keywordPositions,omitempty"`
}

type S关键词信息 struct {
	Keyword      string     `json:"keyword,omitempty"`
	SearchResult bool       `json:"searchResult,omitempty"`
	Positions    []S关键词页面信息 `json:"positions,omitempty"`
}

type S关键词页面信息 struct {
	PageNum     int      `json:"pageNum,omitempty"`
	Coordinates []S关键词坐标 `json:"coordinates,omitempty"`
}
type S关键词坐标 struct {
	PositionX float64 `json:"positionX,omitempty"`
	PositionY float64 `json:"positionY,omitempty"`
}

type S发起签署 struct {
	Docs           []*Doc          `json:"docs,omitempty"`
	SignFlowConfig *SignFlowConfig `json:"signFlowConfig,omitempty"`
	Signers        []*Signers      `json:"signers,omitempty"`
}

// https://open.esign.cn/doc/opendoc/pdf-sign3/su5g42
type SignFlowConfig struct {
	SignFlowTitle      string         `json:"signFlowTitle,omitempty"`      //签署流程主题
	SignFlowExpireTime int64          `json:"signFlowExpireTime,omitempty"` //签署截止时间,默认在签署流程创建后的90天时截止
	AutoStart          bool           `json:"autoStart,omitempty"`          //自动开启签署流程，默认值 true
	AutoFinish         bool           `json:"autoFinish,omitempty"`         //所有签署方签署完成后流程自动完结，默认值 false
	IdentityVerify     bool           `json:"identityVerify,omitempty"`     //身份校验配置项（当开发者指定的签署人信息与该签署人在e签宝已有的身份信息不一致时如何处理）
	NotifyUrl          string         `json:"notifyUrl,omitempty"`          //回调Url
	RedirectConfig     RedirectConfig `json:"redirectConfig,omitempty"`     //回调Url
}

// 创建个人账号json信息配置
type RedirectConfig struct {
	RedirectUrl       string `json:"redirectUrl,omitempty"`
	RedirectDelayTime int64  `json:"redirectDelayTime,omitempty"`
}

// 创建企业账号json信息配置
type CreateOrganizationsByThirdPartyUserIdInfo struct {
	ThirdPartyUserId string `json:"thirdPartyUserId,omitempty"`
	Creator          string `json:"creator,omitempty"`
	Name             string `json:"name,omitempty"`
	IdType           string `json:"idType,omitempty"`
	IdNumber         string `json:"idNumber,omitempty"`
	OrgLegalIdNumber string `json:"orgLegalIdNumber,omitempty"`
	OrgLegalName     string `json:"orgLegalName,omitempty"`
}

// 获取文件上传地址json信息配置
type GetFileUploadUrlInfo struct {
	ContentMd5  string `json:"contentMd5,omitempty"`
	ContentType string `json:"contentType,omitempty"`
	Convert2Pdf bool   `json:"convert2Pdf,omitempty"`
	FileName    string `json:"fileName,omitempty"`
	FileSize    int64  `json:"fileSize,omitempty"`
}

type Signers struct {
	SignerType    int32          `json:"signerType"`
	SignFields    []Signfield    `json:"signFields,omitempty"`
	PsnSignerInfo *PsnSignerInfo `json:"psnSignerInfo,omitempty"` //个人签署方信息
	OrgSignerInfo *OrgSignerInfo `json:"orgSignerInfo,omitempty"` //机构签署方信息
	SignConfig    *SignConfig    `json:"signConfig,omitempty"`    //机构签署方信息
}

type OrgSignerInfo struct {
	OrgId   string   `json:"orgId,omitempty"`
	OrgName string   `json:"orgName,omitempty"`
	OrgInfo *OrgInfo `json:"orgInfo,omitempty"`
}
type OrgInfo struct {
	OrgIDCardNum  string `json:"orgIDCardNum,omitempty"`
	LegalRepName  string `json:"legalRepName,omitempty"`
	OrgIDCardType string `json:"orgIDCardType,omitempty"`
}
type SignConfig struct {
	SignOrder int32 `json:"signOrder,omitempty"`
}
type PsnSignerInfo struct {
	PsnAccount string  `json:"psnAccount,omitempty"`
	PsnInfo    PsnInfo `json:"psnInfo,omitempty"`
}
type PsnInfo struct {
	PsnName      string `json:"psnName,omitempty"`
	PsnIDCardNum string `json:"psnIDCardNum,omitempty"`
}
type SignerAccount struct {
	SignerAccountId     string `json:"signerAccountId,omitempty"`
	AuthorizedAccountId string `json:"authorizedAccountId,omitempty"`
}

type Signfield struct {
	FileId                string                `json:"fileId,omitempty"`
	SignFieldType         int32                 `json:"signFieldType,omitempty"`
	NormalSignFieldConfig NormalSignFieldConfig `json:"normalSignFieldConfig,omitempty"`
}

type NormalSignFieldConfig struct {
	FreeMode          bool              `json:"freeMode,omitempty"`
	AutoSign          bool              `json:"autoSign,omitempty"`
	SignFieldStyle    int32             `json:"signFieldStyle,omitempty"`
	AssignedSealId    string            `json:"assignedSealId,omitempty"`
	SignFieldPosition SignFieldPosition `json:"signFieldPosition,omitempty"`
}
type SignFieldPosition struct {
	PositionPage int64   `json:"positionPage,omitempty"`
	PositionX    float32 `json:"positionX,omitempty"`
	PositionY    float32 `json:"positionY,omitempty"`
}
type SignDateBean struct {
	FontSize int64   `json:"fontSize,omitempty"`
	Format   string  `json:"format,omitempty"`
	PosPage  int64   `json:"posPage,omitempty"`
	PosX     float32 `json:"posX,omitempty"`
	PosY     float32 `json:"posY,omitempty"`
}

type PosBean struct {
	PosPage        string  `json:"posPage,omitempty"`
	PosX           float32 `json:"posX,omitempty"`
	PosY           float32 `json:"posY,omitempty"`
	AddSignTime    bool    `json:"addSignTime,omitempty"`
	SignTimeFormat string  `json:"signTimeFormat,omitempty"`
}

// e签宝的附件？
type EsignAttachment struct {
	FileId         string `json:"fileId,omitempty"`
	AttachmentName string `json:"attachmentName,omitempty"`
}

type Copier struct {
	CopierAccountId                string `json:"copierAccountId,omitempty"`
	CopierIdentityAccountType      int64  `json:"copierIdentityAccountType,omitempty"`
	PrcopierIdentityAccountIdivate string `json:"copierIdentityAccountId,omitempty"`
}

type Doc struct {
	FileId       string `json:"fileId,omitempty"`
	FileName     string `json:"fileName,omitempty"`
	Encryption   int64  `json:"encryption,omitempty"`
	FilePassword string `json:"filePassword,omitempty"`
}

type EsignNotify struct {
	Action            string `json:"action" form:"action"`
	FlowId            string `json:"flowId" form:"flowId"`
	SignFlowId        string `json:"signFlowId" form:"signFlowId"`
	SignTime          string `json:"signTime" form:"signTime"`
	SignOrder         int32  `json:"signOrder,omitempty"`
	Order             int    `json:"order" form:"order"`
	Timestamp         int64  `json:"timestamp" form:"timestamp"`
	SignResult        int    `json:"signResult" form:"signResult"`
	ThirdOrderNo      string `json:"thirdOrderNo" form:"thirdOrderNo"`
	ResultDescription string `json:"resultDescription" form:"resultDescription"`
	ThirdPartyUserId  string `json:"thirdPartyUserId" form:"thirdPartyUserId"`
}

// 摘要md5
func DohashMd5(body string) (md5Str string) {
	hash := md5.New()
	hash.Write([]byte(body))
	md5Data := hash.Sum(nil)
	return base64.StdEncoding.EncodeToString(md5Data)
}

// 计算文件content-md5
const fileChunk = 8192 // 8KB
func CountFileMd5(filePath string) (string, int64) {
	file, err := os.Open(filePath)
	if err != nil {
		return err.Error(), 0
	}
	defer file.Close()

	info, _ := file.Stat()
	fileSize := info.Size()

	blocks := int64(math.Ceil(float64(fileSize) / float64(fileChunk)))
	hash := md5.New()

	for i := int64(0); i < blocks; i++ {
		blockSize := int(math.Min(fileChunk, float64(fileSize-int64(i*fileChunk))))
		buf := make([]byte, blockSize)

		file.Read(buf)
		io.WriteString(hash, string(buf))
	}

	return base64.StdEncoding.EncodeToString(hash.Sum(nil)), fileSize
}
